"""
企业级金融数据MCP服务系统 - API网关
提供RESTful API接口，集成MCP服务和数据同步服务
"""

import asyncio
import logging
from datetime import datetime, timezone, timedelta
from typing import Dict, List, Optional, Any, Union
from fastapi import FastAPI, HTTPException, Depends, Query, Path, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
import uvicorn
from contextlib import asynccontextmanager

from .core.config import config
from .core.database import db_manager
from .core.cache import cache_manager
from .core.exceptions import BaseFinancialMCPException, ErrorCode
from .data_sync_service import data_sync_service, DataSource, SyncType
from .models.stock import (
    StockBasicInfo, StockDailyData, StockMinuteData, StockTickData,
    StockFinancialData, StockHolderData, StockDividendData, StockMarginData
)
from .models.index import IndexBasicInfo, IndexDailyData
from .models.fund import FundBasicInfo, FundNetValue
from .models.bond import BondBasicInfo, BondDailyData
from .models.base import DataSyncTask, DataValidationRule

logger = logging.getLogger(__name__)


# Pydantic模型定义
class APIResponse(BaseModel):
    """API响应基础模型"""
    success: bool = True
    message: str = "操作成功"
    data: Optional[Any] = None
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    request_id: Optional[str] = None


class ErrorResponse(BaseModel):
    """错误响应模型"""
    success: bool = False
    error_code: str
    error_message: str
    details: Optional[Dict[str, Any]] = None
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))


class PaginationParams(BaseModel):
    """分页参数"""
    page: int = Field(default=1, ge=1, description="页码")
    page_size: int = Field(default=20, ge=1, le=100, description="每页大小")


class DateRangeParams(BaseModel):
    """日期范围参数"""
    start_date: Optional[datetime] = Field(default=None, description="开始日期")
    end_date: Optional[datetime] = Field(default=None, description="结束日期")


class StockQueryParams(BaseModel):
    """股票查询参数"""
    symbol: Optional[str] = Field(default=None, description="股票代码")
    symbols: Optional[List[str]] = Field(default=None, description="股票代码列表")
    market: Optional[str] = Field(default=None, description="市场类型")
    industry: Optional[str] = Field(default=None, description="行业分类")


class SyncTaskRequest(BaseModel):
    """同步任务请求"""
    data_source: str = Field(..., description="数据源")
    sync_type: str = Field(..., description="同步类型")
    params: Optional[Dict[str, Any]] = Field(default=None, description="同步参数")
    immediate: bool = Field(default=False, description="是否立即执行")


# API网关类
class FinancialDataAPIGateway:
    """金融数据API网关"""
    
    def __init__(self):
        self.app = FastAPI(
            title="企业级金融数据MCP服务API",
            description="提供完整的金融数据查询、同步和管理功能",
            version="1.0.0",
            docs_url="/docs",
            redoc_url="/redoc"
        )
        self.logger = logging.getLogger(f"{__name__}.FinancialDataAPIGateway")
        self._setup_middleware()
        self._setup_routes()
        self._setup_exception_handlers()
    
    def _setup_middleware(self):
        """设置中间件"""
        # CORS中间件
        self.app.add_middleware(
            CORSMiddleware,
            allow_origins=config.security.cors_origins,
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"],
        )
        
        # Gzip压缩中间件
        self.app.add_middleware(GZipMiddleware, minimum_size=1000)
    
    def _setup_exception_handlers(self):
        """设置异常处理器"""
        
        @self.app.exception_handler(BaseFinancialMCPException)
        async def financial_exception_handler(request, exc: BaseFinancialMCPException):
            return JSONResponse(
                status_code=400,
                content=ErrorResponse(
                    error_code=str(exc.error_code.value),
                    error_message=str(exc),
                    details=exc.details
                ).dict()
            )
        
        @self.app.exception_handler(HTTPException)
        async def http_exception_handler(request, exc: HTTPException):
            return JSONResponse(
                status_code=exc.status_code,
                content=ErrorResponse(
                    error_code="HTTP_ERROR",
                    error_message=exc.detail
                ).dict()
            )
        
        @self.app.exception_handler(Exception)
        async def general_exception_handler(request, exc: Exception):
            self.logger.error(f"未处理的异常: {exc}", exc_info=True)
            return JSONResponse(
                status_code=500,
                content=ErrorResponse(
                    error_code="INTERNAL_ERROR",
                    error_message="内部服务器错误"
                ).dict()
            )
    
    def _setup_routes(self):
        """设置路由"""
        
        # 健康检查
        @self.app.get("/health", response_model=APIResponse)
        async def health_check():
            """健康检查接口"""
            try:
                # 检查数据库连接
                async with db_manager.get_session() as session:
                    from sqlalchemy import text
                    await session.execute(text("SELECT 1"))
                
                # 检查缓存连接
                cache = cache_manager.get_cache("health_check")
                await cache.set("health_check", "ok", ttl=60)
                
                return APIResponse(
                    message="服务运行正常",
                    data={
                        "database": "connected",
                        "cache": "connected",
                        "sync_service": "running" if not data_sync_service._stop_event.is_set() else "stopped"
                    }
                )
            except Exception as e:
                raise HTTPException(status_code=503, detail=f"服务不可用: {e}")
        
        # 股票数据接口
        @self.app.get("/api/v1/stocks/basic", response_model=APIResponse)
        async def get_stocks_basic(
            pagination: PaginationParams = Depends(),
            query_params: StockQueryParams = Depends()
        ):
            """获取股票基本信息"""
            try:
                # 构建查询条件
                filters = {}
                if query_params.symbol:
                    filters['stock_code'] = query_params.symbol
                if query_params.market:
                    filters['market'] = query_params.market
                if query_params.industry:
                    filters['industry'] = query_params.industry
                
                # 查询数据
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(StockBasicInfo)
                    
                    # 应用过滤条件
                    for key, value in filters.items():
                        if hasattr(StockBasicInfo, key):
                            query = query.where(getattr(StockBasicInfo, key) == value)
                    
                    # 分页
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(StockBasicInfo)
                    for key, value in filters.items():
                        if hasattr(StockBasicInfo, key):
                            count_query = count_query.where(getattr(StockBasicInfo, key) == value)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                return APIResponse(
                    data={
                        "items": [self._model_to_dict(item) for item in results],
                        "pagination": {
                            "page": pagination.page,
                            "page_size": pagination.page_size,
                            "total": total,
                            "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                        }
                    }
                )
            except Exception as e:
                self.logger.error(f"获取股票基本信息失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/stocks/{symbol}/daily", response_model=APIResponse)
        async def get_stock_daily_data(
            symbol: str = Path(..., description="股票代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取股票日线数据"""
            try:
                # 先检查缓存
                cache_key = f"stock_daily_{symbol}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("stock_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(StockDailyData).where(
                        StockDailyData.stock_code == symbol
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(StockDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(StockDailyData.trade_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(StockDailyData.trade_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(StockDailyData).where(
                        StockDailyData.stock_code == symbol
                    )
                    if date_range.start_date:
                        count_query = count_query.where(StockDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(StockDailyData.trade_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "symbol": symbol,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取股票日线数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/stocks/{symbol}/realtime", response_model=APIResponse)
        async def get_stock_realtime_data(
            symbol: str = Path(..., description="股票代码")
        ):
            """获取股票实时数据"""
            try:
                # 优先从缓存获取
                cache_key = f"stock_realtime_{symbol}"
                cache = cache_manager.get_cache("realtime_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 从数据库获取最新数据
                async with db_manager.get_session() as session:
                    from sqlalchemy import select
                    query = select(StockMinuteData).where(
                        StockMinuteData.stock_code == symbol
                    ).order_by(StockMinuteData.trade_time.desc())
                    result = await session.execute(query)
                    result = result.scalars().first()
                
                if not result:
                    raise HTTPException(status_code=404, detail="未找到股票实时数据")
                
                data = self._model_to_dict(result)
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=60)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取股票实时数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 指数数据接口
        @self.app.get("/api/v1/indices/basic", response_model=APIResponse)
        async def get_indices_basic(
            pagination: PaginationParams = Depends()
        ):
            """获取指数基本信息"""
            try:
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(IndexBasicInfo)
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(IndexBasicInfo)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                return APIResponse(
                    data={
                        "items": [self._model_to_dict(item) for item in results],
                        "pagination": {
                            "page": pagination.page,
                            "page_size": pagination.page_size,
                            "total": total,
                            "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                        }
                    }
                )
            except Exception as e:
                self.logger.error(f"获取指数基本信息失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/indices/{index_code}/daily", response_model=APIResponse)
        async def get_index_daily_data(
            index_code: str = Path(..., description="指数代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取指数日线数据"""
            try:
                # 先检查缓存
                cache_key = f"index_daily_{index_code}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("index_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(IndexDailyData).where(
                        IndexDailyData.index_code == index_code
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(IndexDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(IndexDailyData.trade_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(IndexDailyData.trade_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(IndexDailyData).where(
                        IndexDailyData.index_code == index_code
                    )
                    if date_range.start_date:
                        count_query = count_query.where(IndexDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(IndexDailyData.trade_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "index_code": index_code,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取指数日线数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/indices/{index_code}/realtime", response_model=APIResponse)
        async def get_index_realtime_data(
            index_code: str = Path(..., description="指数代码")
        ):
            """获取指数实时数据"""
            try:
                # 先检查缓存
                cache_key = f"index_realtime_{index_code}"
                cache = cache_manager.get_cache("index_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select
                    query = select(IndexRealtimeData).where(
                        IndexRealtimeData.index_code == index_code
                    ).order_by(IndexRealtimeData.trade_time.desc()).limit(1)
                    
                    result = await session.execute(query)
                    result = result.scalars().first()
                    
                    if not result:
                        raise HTTPException(status_code=404, detail=f"未找到指数 {index_code} 的实时数据")
                
                data = {
                    "index_code": index_code,
                    "data": self._model_to_dict(result)
                }
                
                # 缓存结果（较短时间）
                await cache.set(cache_key, data, ttl=60)
                
                return APIResponse(data=data)
                
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"获取指数实时数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 基金数据接口
        @self.app.get("/api/v1/funds/basic", response_model=APIResponse)
        async def get_funds_basic(
            pagination: PaginationParams = Depends()
        ):
            """获取基金基本信息"""
            try:
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(FundBasicInfo)
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(FundBasicInfo)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                return APIResponse(
                    data={
                        "items": [self._model_to_dict(item) for item in results],
                        "pagination": {
                            "page": pagination.page,
                            "page_size": pagination.page_size,
                            "total": total,
                            "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                        }
                    }
                )
            except Exception as e:
                self.logger.error(f"获取基金基本信息失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/funds/{fund_code}/nav", response_model=APIResponse)
        async def get_fund_nav_data(
            fund_code: str = Path(..., description="基金代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取基金净值数据"""
            try:
                # 先检查缓存
                cache_key = f"fund_nav_{fund_code}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("fund_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(FundNetValue).where(
                        FundNetValue.fund_code == fund_code
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(FundNetValue.nav_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(FundNetValue.nav_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(FundNetValue.nav_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(FundNetValue).where(
                        FundNetValue.fund_code == fund_code
                    )
                    if date_range.start_date:
                        count_query = count_query.where(FundNetValue.nav_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(FundNetValue.nav_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "fund_code": fund_code,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取基金净值数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/funds/{fund_code}/performance", response_model=APIResponse)
        async def get_fund_performance_data(
            fund_code: str = Path(..., description="基金代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取基金业绩数据"""
            try:
                # 先检查缓存
                cache_key = f"fund_performance_{fund_code}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("fund_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(FundPerformance).where(
                        FundPerformance.fund_code == fund_code
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(FundPerformance.stat_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(FundPerformance.stat_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(FundPerformance.stat_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(FundPerformance).where(
                        FundPerformance.fund_code == fund_code
                    )
                    if date_range.start_date:
                        count_query = count_query.where(FundPerformance.stat_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(FundPerformance.stat_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "fund_code": fund_code,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取基金业绩数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 债券数据接口
        @self.app.get("/api/v1/bonds/basic", response_model=APIResponse)
        async def get_bonds_basic(
            pagination: PaginationParams = Depends()
        ):
            """获取债券基本信息"""
            try:
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(BondBasicInfo)
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(BondBasicInfo)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                return APIResponse(
                    data={
                        "items": [self._model_to_dict(item) for item in results],
                        "pagination": {
                            "page": pagination.page,
                            "page_size": pagination.page_size,
                            "total": total,
                            "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                        }
                    }
                )
            except Exception as e:
                self.logger.error(f"获取债券基本信息失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/bonds/{bond_code}/daily", response_model=APIResponse)
        async def get_bond_daily_data(
            bond_code: str = Path(..., description="债券代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取债券日线数据"""
            try:
                # 先检查缓存
                cache_key = f"bond_daily_{bond_code}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("bond_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(BondDailyData).where(
                        BondDailyData.bond_code == bond_code
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(BondDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(BondDailyData.trade_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(BondDailyData.trade_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(BondDailyData).where(
                        BondDailyData.bond_code == bond_code
                    )
                    if date_range.start_date:
                        count_query = count_query.where(BondDailyData.trade_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(BondDailyData.trade_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "bond_code": bond_code,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取债券日线数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.get("/api/v1/bonds/{bond_code}/yield", response_model=APIResponse)
        async def get_bond_yield_data(
            bond_code: str = Path(..., description="债券代码"),
            date_range: DateRangeParams = Depends(),
            pagination: PaginationParams = Depends()
        ):
            """获取债券收益率数据"""
            try:
                # 先检查缓存
                cache_key = f"bond_yield_{bond_code}_{date_range.start_date}_{date_range.end_date}"
                cache = cache_manager.get_cache("bond_data")
                cached_data = await cache.get(cache_key)
                
                if cached_data:
                    return APIResponse(data=cached_data)
                
                # 查询数据库
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(BondYieldData).where(
                        BondYieldData.bond_code == bond_code
                    )
                    
                    # 日期范围过滤
                    if date_range.start_date:
                        query = query.where(BondYieldData.data_date >= date_range.start_date)
                    if date_range.end_date:
                        query = query.where(BondYieldData.data_date <= date_range.end_date)
                    
                    # 排序和分页
                    query = query.order_by(BondYieldData.data_date.desc())
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(BondYieldData).where(
                        BondYieldData.bond_code == bond_code
                    )
                    if date_range.start_date:
                        count_query = count_query.where(BondYieldData.data_date >= date_range.start_date)
                    if date_range.end_date:
                        count_query = count_query.where(BondYieldData.data_date <= date_range.end_date)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                data = {
                    "bond_code": bond_code,
                    "items": [self._model_to_dict(item) for item in results],
                    "pagination": {
                        "page": pagination.page,
                        "page_size": pagination.page_size,
                        "total": total,
                        "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                    }
                }
                
                # 缓存结果
                await cache.set(cache_key, data, ttl=3600)
                
                return APIResponse(data=data)
                
            except Exception as e:
                self.logger.error(f"获取债券收益率数据失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 数据同步管理接口
        @self.app.get("/api/v1/sync/status", response_model=APIResponse)
        async def get_sync_status():
            """获取数据同步状态"""
            try:
                status = await data_sync_service.get_sync_status()
                return APIResponse(data=status)
            except Exception as e:
                self.logger.error(f"获取同步状态失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.post("/api/v1/sync/start", response_model=APIResponse)
        async def start_sync_service(background_tasks: BackgroundTasks):
            """启动数据同步服务"""
            try:
                background_tasks.add_task(data_sync_service.start)
                return APIResponse(message="数据同步服务启动中")
            except Exception as e:
                self.logger.error(f"启动同步服务失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.post("/api/v1/sync/stop", response_model=APIResponse)
        async def stop_sync_service(background_tasks: BackgroundTasks):
            """停止数据同步服务"""
            try:
                background_tasks.add_task(data_sync_service.stop)
                return APIResponse(message="数据同步服务停止中")
            except Exception as e:
                self.logger.error(f"停止同步服务失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        @self.app.post("/api/v1/sync/trigger", response_model=APIResponse)
        async def trigger_sync_task(
            request: SyncTaskRequest,
            background_tasks: BackgroundTasks
        ):
            """触发特定同步任务"""
            try:
                # 验证数据源和同步类型
                try:
                    data_source = DataSource(request.data_source)
                    sync_type = SyncType(request.sync_type)
                except ValueError as e:
                    raise HTTPException(status_code=400, detail=f"无效的参数: {e}")
                
                # 如果是立即执行，添加到后台任务
                if request.immediate:
                    background_tasks.add_task(
                        self._execute_immediate_sync,
                        data_source,
                        sync_type,
                        request.params or {}
                    )
                    return APIResponse(message="同步任务已添加到执行队列")
                else:
                    # 更新任务配置
                    task_name = f"{data_source.value}_{sync_type.value}"
                    if task_name in data_sync_service.sync_tasks:
                        task = data_sync_service.sync_tasks[task_name]
                        if request.params:
                            task.params.update(request.params)
                        return APIResponse(message="同步任务配置已更新")
                    else:
                        raise HTTPException(status_code=404, detail="未找到指定的同步任务")
                
            except Exception as e:
                self.logger.error(f"触发同步任务失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 数据验证和质量检查接口
        @self.app.get("/api/v1/validation/rules", response_model=APIResponse)
        async def get_validation_rules(
            pagination: PaginationParams = Depends(),
            table_name: Optional[str] = Query(None, description="表名过滤")
        ):
            """获取数据验证规则"""
            try:
                async with db_manager.get_session() as session:
                    from sqlalchemy import select, func
                    query = select(DataValidationRule)
                    
                    if table_name:
                        query = query.where(DataValidationRule.target_table == table_name)
                    
                    offset = (pagination.page - 1) * pagination.page_size
                    results = await session.execute(query.offset(offset).limit(pagination.page_size))
                    results = results.scalars().all()
                    
                    # 获取总数
                    count_query = select(func.count()).select_from(DataValidationRule)
                    if table_name:
                        count_query = count_query.where(DataValidationRule.target_table == table_name)
                    total_result = await session.execute(count_query)
                    total = total_result.scalar()
                
                return APIResponse(
                    data={
                        "items": [self._model_to_dict(item) for item in results],
                        "pagination": {
                            "page": pagination.page,
                            "page_size": pagination.page_size,
                            "total": total,
                            "pages": ((total or 0) + pagination.page_size - 1) // pagination.page_size if pagination.page_size > 0 else 0
                        }
                    }
                )
            except Exception as e:
                self.logger.error(f"获取验证规则失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
        
        # 系统统计接口
        @self.app.get("/api/v1/stats/overview", response_model=APIResponse)
        async def get_system_overview():
            """获取系统概览统计"""
            try:
                async with db_manager.get_session() as session:
                    # 统计各类数据数量
                    stats = {}
                    
                    # 股票数据统计
                    from sqlalchemy import select, func
                    stock_result = await session.execute(select(func.count()).select_from(StockBasicInfo))
                    stock_count = stock_result.scalar()
                    stats['stocks'] = stock_count
                    
                    # 指数数据统计
                    index_result = await session.execute(select(func.count()).select_from(IndexBasicInfo))
                    index_count = index_result.scalar()
                    stats['indices'] = index_count
                    
                    # 基金数据统计
                    fund_result = await session.execute(select(func.count()).select_from(FundBasicInfo))
                    fund_count = fund_result.scalar()
                    stats['funds'] = fund_count
                    
                    # 债券数据统计
                    bond_result = await session.execute(select(func.count()).select_from(BondBasicInfo))
                    bond_count = bond_result.scalar()
                    stats['bonds'] = bond_count
                    
                    # 同步任务统计
                    sync_stats = await data_sync_service._get_sync_statistics()
                    stats['sync_statistics'] = sync_stats
                
                return APIResponse(data=stats)
                
            except Exception as e:
                self.logger.error(f"获取系统概览失败: {e}")
                raise HTTPException(status_code=500, detail=str(e))
    
    async def _execute_immediate_sync(self, data_source: DataSource, 
                                    sync_type: SyncType, params: Dict[str, Any]):
        """执行立即同步任务"""
        try:
            # 这里可以实现立即同步的逻辑
            # 暂时记录日志
            self.logger.info(f"执行立即同步: {data_source.value}, {sync_type.value}, {params}")
        except Exception as e:
            self.logger.error(f"立即同步执行失败: {e}")
    
    def _model_to_dict(self, model) -> Dict[str, Any]:
        """将SQLAlchemy模型转换为字典"""
        if model is None:
            return {}
        
        result = {}
        for column in model.__table__.columns:
            value = getattr(model, column.name)
            # 处理日期时间类型
            if isinstance(value, datetime):
                result[column.name] = value.isoformat()
            else:
                result[column.name] = value
        return result


# 应用生命周期管理
@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动时初始化
    logger.info("启动API网关服务")
    
    try:
        # 初始化数据库
        await db_manager.initialize()
        
        # 初始化缓存
        await cache_manager.initialize()
        
        # 初始化数据同步服务
        await data_sync_service.initialize()
        
        logger.info("API网关服务启动完成")
        
        yield
        
    finally:
        # 关闭时清理
        logger.info("关闭API网关服务")
        
        try:
            # 停止数据同步服务
            await data_sync_service.stop()
            
            # 关闭数据库连接
            await db_manager.close()
            
            # 关闭缓存连接
            await cache_manager.close()
            
        except Exception as e:
            logger.error(f"关闭服务时出错: {e}")


# 创建API网关实例
api_gateway = FinancialDataAPIGateway()
api_gateway.app.router.lifespan_context = lifespan

# 导出FastAPI应用
app = api_gateway.app


async def start_api_server(host: str = "0.0.0.0", port: int = 8000):
    """启动API服务器"""
    config_obj = uvicorn.Config(
        app=app,
        host=host,
        port=port,
        log_level="info",
        access_log=True,
        reload=False
    )
    
    server = uvicorn.Server(config_obj)
    await server.serve()


if __name__ == "__main__":
    # 直接运行时启动服务器
    asyncio.run(start_api_server())